#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>


#define BALEIRO	0
#define CHEO	1
#define MUTEX	2

#define MAL_PARAM 	0
#define XERAL		1
#define PROPIO		2

#define SEM_KEY		0x100
#define SHM_KEY		0x200

#define TRUE		1
#define FALSE		0

#define MAX_ITEMS	50

typedef int semaforo;

void sair(int codigo, char *frase) {
	char s[200];

	switch (codigo) {
	case MAL_PARAM:
		if (frase != NULL)
			sprintf(s, "Mal os parametros.\nUsar: %s\n", frase);
		break;
	case XERAL:
		if (frase != NULL)
			sprintf(s, "%s: %s\n", frase, strerror(errno));
		else
			sprintf(s, "Erro: %s", strerror(errno));
		break;
	case PROPIO:
		if (frase != NULL)
			sprintf(s, "%s\n", frase);
		break;
	}
	write(2, s, strlen(s));
	exit(EXIT_FAILURE);
}

#include "memCompartida.h"

int obterSemaforos(int crear) {
	int flags = 0666;
	if (crear) flags = flags | IPC_CREAT | IPC_EXCL;

	int semid = semget(SEM_KEY, 3, flags);
	if (semid == -1) sair(XERAL, "Obtendo semaforos");
	return semid;
}

void crearSemaforos() {
	obterSemaforos(TRUE);
}

void eliminarSemaforos() {
	int semid = obterSemaforos(FALSE);
	if (semctl(semid, 0, IPC_RMID) == -1)
		sair(XERAL, "Eliminando semaforos");
}

void inicializarSemaforo(semaforo s, int valor) {
	int semid = obterSemaforos(FALSE);
	
	if(semctl(semid, s, SETVAL, valor) == -1) {
		char erro[100];
		sprintf(erro, "inicializando o semaforo %i a %i", s, valor);
		sair(XERAL, erro);
	}
}

void P(semaforo s) {
	int semid = obterSemaforos(FALSE);
	
	struct sembuf sops[1];
	sops[0].sem_num = s;
	sops[0].sem_op = -1;
	sops[0].sem_flg = 0;
	if (semop(semid, sops, 1) == -1) {
		char erro[100];
		sprintf(erro, "Erro facendo P sobre %i", s);
		sair(XERAL, erro);
	}
}

void V(semaforo s) {
	int semid = obterSemaforos(FALSE);

	struct sembuf sops[1];
	sops[0].sem_num = s;
	sops[0].sem_op = 1;
	sops[0].sem_flg = 0;
	if (semop(semid, sops, 1) == -1) {
		char erro[100];
		sprintf(erro, "Erro facendo V sobre %i", s);
		sair(XERAL, erro);
	}
}

